|
1 # Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca> |
|
2 # |
|
3 # This program is free software; you can redistribute it and/or modify |
|
4 # it under the terms of the GNU General Public License as published by |
|
5 # the Free Software Foundation; either version 2 of the License, or |
|
6 # (at your option) any later version. |
|
7 # |
|
8 # This program is distributed in the hope that it will be useful, |
|
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 # GNU General Public License for more details. |
|
12 # |
|
13 # You should have received a copy of the GNU General Public License |
|
14 # along with this program; if not, write to the Free Software |
|
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
16 |
|
17 import config |
|
18 |
|
19 ok = 0 |
|
20 bad = 1 |
|
21 err = 2 |
|
22 econn = 3 |
|
23 |
|
24 class Bad(Exception): pass |
|
25 class Error(Exception): pass |
|
26 class Econn(Exception): pass |
|
27 |
|
28 def encode_int(i): |
|
29 return chr((i/256)%256) + chr(i%256) |
|
30 |
|
31 def encode_str(str): |
|
32 return encode_int(len(str)) + str |
|
33 |
|
34 class Command: |
|
35 def __init__(self, name, args): |
|
36 self.name = name |
|
37 self.args = args |
|
38 |
|
39 def encode(self): |
|
40 argcount = len(self.args) |
|
41 cmd = chr(argcount) + encode_str(self.name) |
|
42 for i in range(argcount): |
|
43 cmd = cmd + encode_str(self.args[i]) |
|
44 cmd = chr(2) + encode_int(len(cmd)) + cmd |
|
45 return cmd |
|
46 |
|
47 class Daemon: |
|
48 def __init__(self): |
|
49 self.socket_file = config.read('socket-file', '/tmp/.vmailmgrd') |
|
50 self.socket = None |
|
51 |
|
52 def connect(self): |
|
53 import socket |
|
54 self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
|
55 self.socket.connect(self.socket_file) |
|
56 |
|
57 def read_response_noraise(self): |
|
58 try: |
|
59 reply = self.socket.recv(3) |
|
60 code = ord(reply[0]) |
|
61 msglen = ord(reply[1])*256 + ord(reply[2]) |
|
62 message = self.socket.recv(msglen) |
|
63 except: |
|
64 return (econn, 'Server aborted the connection') |
|
65 return (code, message) |
|
66 |
|
67 def read_response(self): |
|
68 (code, message) = self.read_response_noraise() |
|
69 if code == err: |
|
70 raise Error, message |
|
71 if code == bad: |
|
72 raise Bad, message |
|
73 if code == econn: |
|
74 raise Econn, message |
|
75 return message |
|
76 |
|
77 def execute(self, command): |
|
78 try: |
|
79 self.connect() |
|
80 except: |
|
81 raise Econn, "Unable to connect to the server" |
|
82 data = command.encode() |
|
83 try: |
|
84 self.socket.send(data) |
|
85 except: |
|
86 raise Econn, "Server aborted the connection" |
|
87 # Don't close the socket here -- it will be closed |
|
88 # as soon as it gets garbage collected, and remains |
|
89 # usable for other commands like listdomain. |
|
90 return self.read_response() |
|
91 |
|
92 def execute(command, args): |
|
93 return Daemon().execute(Command(command, args)) |